package owg.util.userInput;

import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

public class KeyboardState implements AWTEventListener
{
    public static final int NUM_KEYCODES = 128;
    private static boolean isRegistered = false;

    private static boolean[] keyPresses = new boolean[NUM_KEYCODES];

    public static void register()
    {
	if(!isRegistered)
	{
	    Toolkit.getDefaultToolkit().addAWTEventListener(new KeyboardState(), -1);//Capture all events to update modifier mask
	    isRegistered = true;
	}
    }
    /**
     * Get whether the indicated key(e.g. KeyEvent.VK_SPACE) is down.
     * @param keyCode The virtual key code to check. Must be between 0 and NUM_KEYCODES.
     * @return Whether the key state is down. This may fail if the user changes the window focus while pressing or releasing keys.
     * @throws IllegalArgumentException If the key code is out of range.
     */
    public static boolean isKeyDown(int keyCode) throws IllegalArgumentException
    {
	if(keyCode >= NUM_KEYCODES)
	    throw new IllegalArgumentException("Key Code out of range: "+keyCode);
	register();
	return keyPresses[keyCode];
    }


    @Override
    public void eventDispatched(AWTEvent event)
    {
	if(event instanceof InputEvent)
	{
	    keyPresses[KeyEvent.VK_CONTROL] = ((InputEvent) event).isControlDown();
	    keyPresses[KeyEvent.VK_ALT] = ((InputEvent) event).isAltDown();
	    keyPresses[KeyEvent.VK_SHIFT] = ((InputEvent) event).isShiftDown();
	    keyPresses[KeyEvent.VK_ALT_GRAPH] = ((InputEvent) event).isAltGraphDown();
	}
	
	if(!(event instanceof KeyEvent))
	    return;
	
	KeyEvent e = (KeyEvent) event;
	int code = e.getKeyCode();
	if(code >= NUM_KEYCODES)
	    return;
	if(e.getID() == KeyEvent.KEY_PRESSED)
	    keyPresses[code] = true;
	else if(e.getID() == KeyEvent.KEY_RELEASED)
	    keyPresses[code] = false;
    }
    public static int getModifierMask()
    {
	int mask = 0;
	if(keyPresses[KeyEvent.VK_CONTROL])
	    mask |= KeyEvent.CTRL_DOWN_MASK;
	if(keyPresses[KeyEvent.VK_ALT])
	    mask |= KeyEvent.ALT_DOWN_MASK;
	if(keyPresses[KeyEvent.VK_SHIFT])
	    mask |= KeyEvent.SHIFT_DOWN_MASK;
	if(keyPresses[KeyEvent.VK_ALT_GRAPH])
	    mask |= KeyEvent.ALT_GRAPH_DOWN_MASK;
	return mask;
    }
}
